/**
* \file DGVMainVTK.h
*
* \brief This file defines a class for the Main Window in DGV applications.
* \author Shekhar S. Chandra, 2008
*
* This file is part of DGV Library.
*
* DGV is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* DGV is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with DGV.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef DGVMAINVTK_H_INCLUDED
#define DGVMAINVTK_H_INCLUDED

#include <QtGui/QMainWindow> //For base class
#include <QtCore/QSignalMapper>

#include "DGVConsole.h"
#include "DGVImage.h"
#include "DGVImageVTK.h"
#include "DGVLatticeVTK.h"
#include "DGVDiophantineVTK.h"
#include "DGVTransform.h"

/*!
    \class DGVMainVTK
    \brief This class represents the DGV Main Window object when using VTK classes.
    \author Shekhar S. Chandra, 2008-2010

    The class represents the DGV Main Window object using the Qt Library.
    It contains a Workspace environment for the user and subsequent operations critical for the User Interface (UI) of the Discrete Geometry Viewer (DGV) program.
*/
class DGV_VTK_EXPORT DGVMainVTK : public QMainWindow
{
    Q_OBJECT

public:
    /*!
        \fn DGVMainVTK::DGVMainVTK(QWidget *parent = 0)
        \brief The standard constructor
    */
    DGVMainVTK(QWidget *parent = 0);
    /*!
        \fn DGVMainVTK::~DGVMainVTK()
        \brief The standard destructor
    */
    ~DGVMainVTK();

    /**
        \fn DGVMainVTK::addWindowToWorkspace(QWidget *win)
        \brief Adds widget into workspace.
    */
    inline void addWindowToWorkspace(QWidget *win)
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->addWindow(win);  }
    /**
        \fn DGVMainVTK::addImage(DGVImageVTK *img)
        \brief Adds an image widget and links its results and tables.
    */
    void addImage(DGVImageVTK *img);
    /**
        \fn DGVMainVTK::addImage(DGVImage *img)
        \brief Adds an image widget and links its results and tables.
    */
    void addImage(DGVImage *img);
    /**
        \fn DGVMainVTK::addTable(DGVTable *tbl)
        \brief Adds a table widget and links its results and tables.
    */
    void addTable(DGVTable *tbl);
    /**
        \fn DGVMainVTK::addTable(DGVTableVTK *tbl)
        \brief Adds a table widget and links its results and tables.
    */
    void addTable(DGVTableVTK *tbl);
    /**
        \fn DGVMainVTK::addPlot(DGVPlot *plot)
        \brief Adds a plot widget and links its results and tables.
    */
    void addPlot(DGVPlot *plot);
    /**
        \fn DGVMainVTK::addPlot(DGVPlotVTK *plot)
        \brief Adds a plot widget and links its results and tables.
    */
    void addPlot(DGVPlotVTK *plot);
    /**
        \fn DGVMainVTK::addScan(DGVAnimatedScan *scan)
        \brief Adds a scan widget and links its results and tables.
    */
    void addScan(DGVAnimatedScan *scan);
    /**
        \fn DGVMainVTK::addSurfacePlot(DGVSurfacePlotVTK *plot)
        \brief Adds a surface plot widget and links its results and tables.
    */
    void addSurfacePlot(DGVSurfacePlotVTK *plot);
    /**
        \fn DGVMainVTK::addVolumePlot(DGVVolumePlotVTK *plot)
        \brief Adds a volume plot widget and links its results and tables.
    */
    void addVolumePlot(DGVVolumePlotVTK *plot);
    /**
        \fn DGVMainVTK::addLattice(DGVLatticeVTK *lattice)
        \brief Adds a lattice widget.
    */
    void addLattice(DGVLatticeVTK *lattice);
    /**
        \fn DGVMainVTK::loadFile(const QString &filename)
        \brief Loads the file with filename directly for analysis and display.
    */
    bool loadFile(const QString &filename);
    /**
        \fn DGVMainVTK::loadFiles(const QStringList &filenames)
        \brief Loads files with filenames directly for analysis and display.
    */
    void loadFiles(const QStringList &filenames);
    /**
        \fn DGVMainVTK::loadStack(const QString &filenames)
        \brief Loads an image stack with filename directly for analysis and display.
    */
    bool loadStack(const QString &filenames);
    /*!
        \fn DGVMainVTK::activeData()
        \brief Returns the data of the active window regardless of being an image, table or surface plot.
    */
    Array<imageType,2>* activeData();
    /*!
        \fn DGVMainVTK::activeViewedData()
        \brief Returns the data being viewed from the active window regardless of being an image, table or surface plot.
    */
    Array<imageType,2>* activeViewedData();
    /*!
        \fn DGVMainVTK::activeDataComplex()
        \brief Returns the complex data of the active window regardless of being an image or table.
    */
    Array<complex<imageType>,2>* activeDataComplex();
    /*!
        \fn DGVMainVTK::isActiveDataComplex()
        \brief Returns true if the data of the active window is complex regardless of window type.
    */
    bool isActiveDataComplex();
    /*!
        \fn DGVMainVTK::activeName()
        \brief Returns the name of the active window regardless of being an image, table or surface plot.
    */
    QString activeName();
    /*!
        \fn DGVMainVTK::activeNamePrefix()
        \brief Returns the name with prefix of the active window regardless of being an image, table or surface plot.
    */
    QString activeNamePrefix();

public slots:
    /*!
        \fn DGVMainVTK::displayImage(DGVImageVTK *img)
        \brief Handles the displaying of result as they are produced.
    */
    void displayImage(DGVImageVTK *img);
    /*!
        \fn DGVMainVTK::displayImage(DGVImage *img)
        \brief Handles the displaying of result as they are produced.
    */
    void displayImage(DGVImage *img);
    /*!
        \fn DGVMainVTK::displayTable(DGVTable *newTable)
        \brief Handles the displaying of tables as they are produced.
    */
    void displayTable(DGVTable *newTable);
    /*!
        \fn DGVMainVTK::displayTable(DGVTableVTK *newTable)
        \brief Handles the displaying of tables as they are produced.
    */
    void displayTable(DGVTableVTK *newTable);
    /*!
        \fn DGVMainVTK::displayPlot(DGVPlot *newPlot)
        \brief Handles the displaying of plots as they are produced.
    */
    void displayPlot(DGVPlot *newPlot);
    /*!
        \fn DGVMainVTK::displayPlot(DGVPlotVTK *newPlot)
        \brief Handles the displaying of plots as they are produced.
    */
    void displayPlot(DGVPlotVTK *newPlot);
    /*!
        \fn DGVMainVTK::displayScan(DGVAnimatedScan *newScan)
        \brief Handles the displaying of scans as they are produced.
    */
    void displayScan(DGVAnimatedScan *newScan);
    /*!
        \fn DGVMainVTK::displaySurfacePlot(DGVSurfacePlotVTK *newPlot)
        \brief Handles the displaying of surface plots as they are produced.
    */
    void displaySurfacePlot(DGVSurfacePlotVTK *newPlot);
    /*!
        \fn DGVMainVTK::displayVolumePlot(DGVVolumePlotVTK *newPlot)
        \brief Handles the displaying of volume plots as they are produced.
    */
    void displayVolumePlot(DGVVolumePlotVTK *newPlot);
    /*!
        \fn DGVMainVTK::displayLattice(DGVLatticeVTK *newLattice)
        \brief Handles the displaying of lattice as they are produced.
    */
    void displayLattice(DGVLatticeVTK *newLattice);

    /*!
        \fn DGVMainVTK::createImage(Array<imageType,2> newData, QString imgName)
        \brief Creates an image for display when data is generated (say from transforms).
    */
    void createImage(Array<imageType,2> newData, QString imgName);
    /*!
        \fn DGVMainVTK::createImage(Array< complex<imageType>,2 > newData, QString imgName)
        \brief Creates an image for display when data is generated (say from transforms). Overloaded for complex valued arrays.
    */
    void createImage(Array< complex<imageType>,2 > newData, QString imgName);
    /*!
        \fn DGVMainVTK::createTable(Array<imageType,2> newData, QString tblName)
        \brief Creates a table for display when data is generated (say from transforms).
    */
    void createTable(Array<imageType,2> newData, QString tblName);
    /*!
        \fn DGVMainVTK::createTable(Array< complex<imageType>,2 > newData, QString tblName)
        \brief Creates a table for display when data is generated (say from transforms). Overloaded for complex valued arrays.
    */
    void createTable(Array< complex<imageType>,2 > newData, QString tblName);

    /**
        \fn DGVMainVTK::open()
        \brief Opens image or other files for analysis and display.
    */
    void open();
    /**
        \fn DGVMainVTK::openStack()
        \brief Opens image stack for analysis and display.
    */
    void openStack();
    /**
        \fn DGVMainVTK::openRecentFile()
        \brief Opens recent file (from recent file menu) for analysis and display.
    */
    void openRecentFile();
    /**
        \fn DGVMainVTK::save()
        \brief Saves active window as an image.
    */
    void save();
    /**
        \fn DGVMainVTK::saveNative()
        \brief Saves active window as Native data (in Blitz++ Array File Format) or other files.
    */
    void saveNative();
    /**
        \fn DGVMainVTK::saveStack()
        \brief Saves active window as a stack of images (JPEG, TIFF, BMP or PNM formats).
    */
    void saveStack();
    /**
        \fn DGVMainVTK::newTab()
        \brief Creates a new tab for the workspace.
    */
    void newTab();
    /**
        \fn DGVMainVTK::newTable()
        \brief Creates table for analysis and display.
    */
    void newTable();
    /**
        \fn DGVMainVTK::newImage()
        \brief Creates image for analysis and display.
    */
    void newImage();
    /**
        \fn DGVMainVTK::table()
        \brief Displays table of the data of the active window.
    */
    void table();
    /**
        \fn DGVMainVTK::embed()
        \brief Embeds or crops the data of the active window.
    */
    void embed();
    /**
        \fn DGVMainVTK::operate()
        \brief Performs arithmetic with the data of the active window.
    */
    void operate();
    /**
        \fn DGVMainVTK::centerDC(bool center)
        \brief Sets whether the DC term of the Fast Fourier Transforms are centered.
    */
    inline void centerDC(bool center)
    {   actionCenterDC->setChecked(center);   }
    /**
        \fn DGVMainVTK::FFT()
        \brief Performs the Fast Fourier Transform (FFTW Version) of the active window.
    */
    void FFT();
    /**
        \fn DGVMainVTK::iFFT()
        \brief Performs the Inverse Fast Fourier Transform (FFTW Version) of the active window.
    */
    void iFFT();
    /**
        \fn DGVMainVTK::FFT_Real()
        \brief Performs the Real Fast Fourier Transform (FFTW Version) of the active window.
    */
    void FFT_Real();
    /**
        \fn DGVMainVTK::iFFT_Real()
        \brief Performs the Real Inverse Fast Fourier Transform (FFTW Version) of the active window.
    */
    void iFFT_Real();
    /**
        \fn DGVMainVTK::FFT_1D(Array<Array<complex<tableType>,1>,1> data)
        \brief Performs the 1D Fast Fourier Transform (FFTW Version) of the active window.
    */
    void FFT_1D(Array<Array<complex<tableType>,1>,1> data);
    /**
        \fn DGVMainVTK::iFFT_1D(Array<Array<complex<tableType>,1>,1> data)
        \brief Performs the 1D Inverse Fast Fourier Transform (FFTW Version) of the active window.
    */
    void iFFT_1D(Array<Array<complex<tableType>,1>,1> data);
    /**
        \fn DGVMainVTK::FFT_Real_1D(Array<Array<tableType,1>,1> data)
        \brief Performs the Real 1D Fast Fourier Transform (FFTW Version) of the active window.
    */
    void FFT_Real_1D(Array<Array<tableType,1>,1> data);
    /**
        \fn DGVMainVTK::iFFT_Real_1D(Array<Array<complex<tableType>,1>,1> data)
        \brief Performs the Real 1D Inverse Fast Fourier Transform (FFTW Version) of the active window.
    */
    void iFFT_Real_1D(Array<Array<complex<tableType>,1>,1> data);
    /**
        \fn DGVMainVTK::radonSlices()
        \brief Produces n-1 dimensional Radon slices of Fourier space of the active window.
    */
    void radonSlices();
    /**
        \fn DGVMainVTK::FRT()
        \brief Performs the Finite Radon Transform (FRT) of the active window.
    */
    void FRT();
    /**
        \fn DGVMainVTK::iFRT()
        \brief Performs the Inverse Finite Radon Transform (iFRT) of the active window.
    */
    void iFRT();
    /**
        \fn DGVMainVTK::iFRT_Unscaled()
        \brief Performs the Unscaled Inverse Finite Radon Transform (iFRT) of the active window.
    */
    void iFRT_Unscaled();
    /**
        \fn DGVMainVTK::updateWindowMenu()
        \brief Updates the Windows menu.
    */
    void updateWindowMenu();
    /*!
        \fn DGVMainVTK::setActiveWindow(QWidget *window)
        \brief Set the window active.
    */
    void setActiveWindow(QWidget *window);

    /*!
        \fn DGVMainVTK::setTabName(QWidget *window)
        \brief Set the tab name.
    */
    void setTabName(QWidget *window);
    /*!
        \fn DGVMainVTK::setTabName(const QString newName)
        \brief Set the tab name of the current tab.
    */
    void setTabName(const QString newName);
    /*!
        \fn DGVMainVTK::closeTab(int index)
        \brief Close the tab.
    */
    void closeTab(int index);
    /*!
        \fn DGVMainVTK::closeTabActiveWindow()
        \brief Close active window in the tab.
    */
    inline void closeTabActiveWindow()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->closeActiveWindow();   }
    /*!
        \fn DGVMainVTK::closeTabAllWindows()
        \brief Close all the windows in the current tab.
    */
    inline void closeTabAllWindows()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->closeAllWindows(); }
    /*!
        \fn DGVMainVTK::cascadeTab()
        \brief Cascade all the windows in the current tab.
    */
    inline void cascadeTab()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->cascade(); }
    /*!
        \fn DGVMainVTK::tileTab()
        \brief Tile all the windows in the current tab.
    */
    inline void tileTab()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->tile();    }

    /**
        \fn DGVMainVTK::working()
        \brief Show working status box.
    */
    void working();
    /**
        \fn DGVMainVTK::done()
        \brief Close working status box.
    */
    void done();
    /**
        \fn DGVMainVTK::tile()
        \brief Tile windows within workspace.
    */
    inline void tile()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->tile();  }
    /**
        \fn DGVMainVTK::cascade()
        \brief Cascade windows within workspace.
    */
    inline void cascade()
    {   qobject_cast<QWorkspace *>(workspaces->currentWidget())->cascade();   }

    /*!
        \fn DGVMainVTK::about()
        \brief About Dialog.
    */
    void about();
    void cut();
    void copy();
    void paste();

    /*!
        \fn DGVMainVTK::isActiveImage()
        \brief Returns true if active window is an Image (DGVImageVTK object)
    */
    bool isActiveImage();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVImageVTK object, returns 0 if active window is not a DGVImageVTK object
    */
    DGVImageVTK* activeImage();
    /*!
        \fn DGVMainVTK::isActiveTable()
        \brief Returns true if active window is a Table (DGVTableVTK object)
    */
    bool isActiveTable();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVTableVTK object, returns 0 if active window is not a DGVTableVTK object
    */
    DGVTableVTK* activeTable();
    /*!
        \fn DGVMainVTK::isActiveSPlot()
        \brief Returns true if active window is a Surface Plot (DGVSurfacePlotVTK object)
    */
    bool isActiveSPlot();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVSurfacePlotVTK object, returns 0 if active window is not a DGVSurfacePlotVTK object
    */
    DGVSurfacePlotVTK* activeSPlot();
    /*!
        \fn DGVMainVTK::isActivePlot()
        \brief Returns true if active window is a Plot (DGVPlot object)
    */
    bool isActivePlot();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVPlot object, returns 0 if active window is not a DGVPlot object
    */
    DGVPlot* activePlot();
    /*!
        \fn DGVMainVTK::isActiveVPlot()
        \brief Returns true if active window is a Volume Plot (DGVVolumePlotVTK object)
    */
    bool isActiveVPlot();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVVolumePlotVTK object, returns 0 if active window is not a DGVVolumePlotVTK object
    */
    DGVVolumePlotVTK* activeVPlot();
    /*!
        \fn DGVMainVTK::isActiveLattice()
        \brief Returns true if active window is a Lattice (DGVLatticeVTK object)
    */
    bool isActiveLattice();
    /*!
        \fn DGVMainVTK::activeImage()
        \brief Returns the DGVLatticeVTK object, returns 0 if active window is not a DGVLatticeVTK object
    */
    DGVLatticeVTK* activeLattice();
    /*!
        \fn DGVMainVTK::getConsole()
        \brief Returns the console attached to the window. Messages can be directly passed using this member and DGVConsole members.
    */
    inline DGVConsole* getConsole()
    {   return console; }
    /*!
        \fn DGVMainVTK::setCurrentFile(const QString &fileName)
        \brief Saves the recent opened/saved file into the recent files list.
    */
    void setCurrentFile(const QString &fileName);

protected:
    bool conductingFFT; //!< FFT Flag
    bool conductingFFT_1D; //!< 1D FFT Flag
    bool conductingInverseFFT; //!< iFFT Flag
    bool conductingInverseFFT_1D; //!< 1D iFFT Flag
    QString currentFile; //!< Tracks current file opened.

    QTabWidget *workspaces; //!< Pointer to the Workspace environment for the user.
    QSignalMapper *windowMapper; //!< Used to keep events in workspace in order.

    Array<complex<double>,2> field;

    ///Actions
    enum { MaxRecentFiles = 10 };
    //----File----
    QAction *actionOpen;
    QAction *actionOpenStack;
    QAction *actionSave;
    QAction *actionSaveRaw;
    QAction *actionSaveStack;
    QAction *actionCloseActive;
    QAction *actionCloseAll;
    QAction *actionsRecentFile[MaxRecentFiles];
    QAction *actionRecentFileSeparator;
    QAction *actionExit;
    //----New----
    QAction *actionNewTab;
    QAction *actionNewTable;
    QAction *actionNewImage;
    //----Data----
    QAction *actionTable;
    QAction *actionEmbed;
    QAction *actionOperate;
    //----Transform----
    QAction *actionFFT;
    QAction *actioniFFT;
    QAction *actionFFT_Real;
    QAction *actioniFFT_Real;
    QAction *actionSlice;
    QAction *actionNormalise;
    QAction *actionCenterDC;
    QAction *actionFRT;
    QAction *actioniFRT;
    QAction *actioniFRT_Unscaled;
    //----Windows----
    QAction *actionCascade;
    QAction *actionTile;
    QAction *actionSeparator;
    QAction *actionConsole;
    //----Help----
    QAction *actionAbout;

    ///Menus
    QMenuBar *menuBar;
    QMenu *menuFile;
    QMenu *submenuNew;
    QMenu *menuData;
    QMenu *menuTransform;
    QMenu *submenuFourier;
    QMenu *submenuRadon;
    QMenu *menuWindows;
    QMenu *menuHelp;
    QMenu *contextMenu; //!< Context Menu

    ///Child Conext Menu Vectors (to be passed to children to use.
    QVector<QMenu *> contextMenusToPass;

    ///Working Message
    QProgressDialog *workingDlg;
    bool workingOn; //!< Track if the Working Status Box is active.

    ///DGV Objects
    DGVTransform *Transforms; //!< Wraps all supported Transforms for widgets
    DGVConsole *console; //!< Console dock widget for errors and info messages

    /*!
        \fn DGVMainVTK::createMenu()
        \brief Creates the menu actions.
    */
    void createMenu();
    /*!
        \fn DGVMainVTK::createConnections()
        \brief Creates the signals and slots connections within the main window.
    */
    void createConnections();
    /*!
		\fn DGVMainVTK::contextMenuEvent(QContextMenuEvent *event)
		\brief The context menu setup member
	*/
	void contextMenuEvent(QContextMenuEvent *event);
	/*!
        \fn DGVMainVTK::dragEnterEvent(QDragEnterEvent *event)
        \brief Part of the Drag and Drop feature members. Tells what drags to accept.
    */
	void dragEnterEvent(QDragEnterEvent *event);
	/*!
        \fn DGVMainVTK::dropEvent(QDropEvent *event)
        \brief Part of the Drag and Drop feature members. Opens the dropped files.
    */
	void dropEvent(QDropEvent *event);
	/*!
        \fn DGVMainVTK::closeEvent(QCloseEvent *event)
        \brief Tasks to complete when closing.
    */
	void closeEvent(QCloseEvent *event);
	/*!
        \fn DGVMainVTK::setupTooltips()
        \brief Sets up the tooltips for the main window actions.
    */
    void setupTooltips();
    /*!
        \fn DGVMainVTK::updateRecentFileActions()
        \brief Updates the recent files list in the file menu.
    */
    void updateRecentFileActions();
    /*!
        \fn DGVMainVTK::commonChildProperties(QWidget *widget)
        \brief Sets all the common child properties of the data windows such as images, plots etc.
    */
    void commonChildProperties(QWidget *widget);
    /*!
        \fn DGVMainVTK::strippedName(const QString &fullFileName)
        \brief Returns the filename with the path stripped.
    */
    inline QString strippedName(const QString &fullFileName)
    {   return QFileInfo(fullFileName).fileName(); }

    /*!
        \fn DGVMainVTK::writeSettings()
        \brief Saves the state of the application.
    */
    void writeSettings();
    /*!
        \fn DGVMainVTK::readSettings()
        \brief Loads the state of the application.
    */
    void readSettings();
};

#endif // DGVMAINVTK_H_INCLUDED
